{% extends 'core/Cryptographic Failures/cryptographic_failures.html' %} {% load static %}
This website uses PBKDF2 with SHA256 hashing and salting for its general purposes, as we have no internet
communication with another server. For hashing and encrypting, many already done libraries exist we can use
instead of writing our own. But for the sake of explanation, I will explain in general how we can implement
our own data encryption. Let's start by picking an algorithm. We will use RSA for the explanation, as it's
easier to understand. The explanation is done with python language.
For starters, we must import the libraries we will be using.
import string
import unidecode
import random
from sympy import *
Then we need to generate our keys. So let's make a function for it.
def Generate_Keys():
'''
Generating random prime numbers with randprime function
from sympy library.
'''
p = randprime(0,99999999999999)
q = randprime(0,99999999999999)
'''
All necessary calculations for the key generation, a loop
is used for finding the greatest common divider equal to one.
'''
n = p * q
fi = (p - 1) * (q - 1)
e = random.randint(2,fi + 1)
for _ in iter(int,1):
if gcd(e,fi) == 1:
break
else:
e += 1
d = pow(e, -1, fi)
return p,q,e,n,d
We use this function to generate our private key d and public modulus n
and exponent e. A private key is something we need to keep ourselves. Public
modulus and exponent can be sent to people that will, in return, be sending us encrypted messages. Since
only we have the private key, we can decrypt this communication. In my example, I use 14-digit keys.
However, in the case of safe encryption, using at least a 2048-digit number is recommended. For more
information on keys and their generation, you can visit:
RSA_(cryptosystem).
Since RSA encryption works with binary values, we need a way to convert plaintext into its binary representation.
def to_Bin(input):
'''
Converting characters to their Unicode representation with
ord() function
'''
my_ascii = []
for i in range(len(input)):
my_ascii.append(ord(input[i]))
'''
First, splitting the values into parts of equal length,
in this case, 7. Then converting the Unicode values into
binary strings using the format() function. Then joining
the list of lists into one big list
'''
to_bin = []
x = 7
to_bin += [my_ascii[i: i + x] for i in range(0, len(my_ascii), x)]
for i in range(len(to_bin)):
for j in range(len(to_bin[i])):
to_bin[i][j] = format(to_bin[i][j], "011b")
for i in range(len(to_bin)):
to_bin[i] = ''.join(to_bin[i])
return to_bin
You don't have to follow precisely when implementing yourself, as some choices were my preference, such as splitting the characters by seven and giving the binary numbers length 11. We can encrypt the data now that we have both keys and data prepared.
def Encrypt(input,e,n):
'''
First, we convert input as a string into its binary representation. Then
we turn the binary input into Integers, using [2:] to slice off the 0b
part of the binary. Then we parse the integer number through the formula
using public keys e and n.
'''
input = to_Bin(input)
for i in range(len(input)):
input[i] = int(input[i][2:],2)
input[i] = pow(input[i],e,n)
return input
Now we have encrypted data that can be sent to the person who owns the private key. But what happens when he receives the message?
def Decrypt(input,n,d):
'''
First, we use the decryption formula with our public and
private key.
'''
for i in range(len(input)):
input[i] = pow(input[i],d,n)
output = ''
actuall_output = ''
'''
We start by changing the input into its binary values.
Once that is done, we reverse the binary because how
the format returns our binary would break our code. Then
we count until we reach the eight-bit and convert it back
to Unicode and then to its corresponding character. In the end,
we need to reverse it once again, as the text is backward.
All the reversing is due to how the python compiler works
and interprets binary.
'''
for i in range(len(input)):
bin_value = format(input[i], "011b")
reverse_input = bin_value[::-1]
reverse_input = str(reverse_input)
j = 0
itter = 0
holder = ''
while j < len(reverse_input):
holder += reverse_input[j]
if len(holder) == 8:
j = j + 4
holder = holder[::-1]
reverse = int(holder,2)
output += chr(reverse)
holder = ''
continue
j += 1
holder = holder[::-1]
reverse = int(holder,2)
output += chr(reverse)
actuall_output += output[::-1]
output = ''
return actuall_output
We now have everything we need to try encryption and decryption, so let's see how that looks.
string = Normalize_Data('This is my testing string')
p,q,e,n,d = Generate_Keys()
encrypted_message = Encrypt(string,e,n)
decrypted_message = Decrypt(encrypted_message,n,d)
OUTPUT:
public key e: 986992929925166792117763447
public key n: 3784143317985393602170635019
Testing string: This is my testing string
Encrypted string: [6201854851823893170291, 2365112509239765706867, 8563074209913585768564, 979693170791]
Decrypted string: This is my testing string
This is the showcase of an EXEMPLARY code for RSA encryption.
I don't recommend using this code as it is not optimized for production use and was written only to help get
a better understanding of encryption itself. If you need encryption algorithms, use already-done libraries.
Mixing algorithms together and combining encryption with hashing, salting, and peppering is always
the best way to keep your data safe. Once you encrypt any plaintext using these algorithms, it is virtually
impossible for the attacker to decrypt the data. That is what we use for our passwords. We save only
encrypted passwords into the database, and every time a user logs in, his password is encrypted using the
same methods. If these passwords match, we know to log him in. If an attacker gets their hands on the
passwords, the only thing he can see is unusable gibberish. And without knowing what keys, and hashing,
salting we used, he won't be able to decipher the data.
Example of hashing a password using SHA256:
from hashlib import sha256
input_ = 'superSecretPassword'
print(sha256(input_.encode('utf-8')).hexdigest())
Hashed password: ab5c39620a81e237b66bd49554fc94e8eb23a60e99d01c5f3f0b30e8daee230e
Feel free to try the code yourself.
If you want to better understand RSA encryption you can watch this video from Art of the Problem: